home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr25 / gnuplsrc.zip / GCLIENT.C < prev    next >
C/C++ Source or Header  |  1993-03-21  |  26KB  |  792 lines

  1. #ifdef INCRCSDATA
  2. static char RCSid[]="$Id: gclient.c,v 1.3 1992/07/26 12:58:42 fearick Exp fearick $" ;
  3. #endif
  4.  
  5. /****************************************************************************
  6.  
  7.     PROGRAM: GnuShell
  8.     
  9.     MODULE:  gclient.c
  10.         
  11.     This file contains the client window procedures for GnuShell
  12.  
  13.     Copyright (c) 1992, Roger Fearick.
  14.     All rights reserved
  15.      
  16.     THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT WARRANTIES OF ANY KIND. 
  17.    
  18.     Permission is hereby granted for personal, non-commercial use of this 
  19.     software.You are granted the right to use, modify, and redistribute 
  20.     it for for non-commercial purposes, provided that all copyright 
  21.     notices remain intact and all changes are clearly documented.      
  22.     THE AUTHOR MAKES NO WARRANTY OF ANY KIND WITH RESPECT TO THIS PRODUCT 
  23.     AND EXPLICITLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY 
  24.     OR FITNESS FOR ANY PARTICULAR PURPOSE.                               
  25.     
  26. ****************************************************************************/
  27.  
  28. /* Update Log
  29. **
  30.  * $Log: gclient.c,v $
  31.  * Revision 1.3  1992/07/26  12:58:42  fearick
  32.  * Clean up from 16-bit command buffer
  33.  *
  34.  * Revision 1.2  1992/07/26  12:37:10  fearick
  35.  * Initial 32-bit version
  36.  *
  37.  * Revision 1.1  1992/07/25  15:43:51  fearick
  38.  * Initial revision
  39.  *
  40.  *
  41. */ 
  42.  
  43. #define INCL_PM
  44. #define INCL_WIN
  45. #define INCL_DOSMEMMGR
  46. #define INCL_DOSPROCESS
  47. #define INCL_DOSFILEMGR
  48. #define INCL_DOSNMPIPES
  49. #define INCL_DOSSESMGR
  50. #define INCL_DOSSEMAPHORES
  51. #define INCL_DOSMISC
  52. #include <os2.h>
  53. #include <string.h>
  54. #include <stdio.h>
  55. #include <stdlib.h>
  56. #include <unistd.h>
  57. #include <process.h>
  58. #include "gnushell.h"
  59.  
  60.  
  61. /*==== l o c a l    d a t a ==================================================*/
  62.  
  63.  
  64. static char     szPrintFile[CCHMAXPATH] = { 0 } ;   // for printing to files
  65. static HWND     hWndstart ;     /* used for errors in startup */
  66. static ULONG    pidGnu=0L ;      /* gnuplot pid */
  67. static HPS      hpsScreen ;     /* screen pres. space */
  68.  
  69. static char     szFontNameSize[256] ;
  70. static BOOL     bLineTypes = FALSE ;
  71. static BOOL     bColours = TRUE ;
  72. static HMTX     semCommands ;
  73.  
  74.             /* stuff for screen-draw thread control */
  75.             
  76. static BOOL     bExist ; 
  77. static BOOL     bStopDraw ; 
  78. static HEV      semDrawDone ;
  79. static HEV      semStartDraw ;
  80.  
  81.             /* command buffer */
  82.             
  83. static int ncalloc = 0 ;
  84. static int ic = 0 ;
  85. static char **commands = NULL ;
  86.  
  87. /*==== f u n c t i o n s =====================================================*/
  88.  
  89. MRESULT          WmClientCmdProc( HWND , ULONG, MPARAM, MPARAM ) ; 
  90.  
  91. static void     ThreadDraw( void ) ;
  92. static void     DoPaint( HWND, HPS ) ;
  93. static void     Display( void ) ;
  94. void            SelectFont( HPS, char *, short, long );
  95. void            SpawnGnu( void ) ;
  96.  
  97.  
  98.  
  99. /*==== c o d e ===============================================================*/
  100.  
  101. MRESULT EXPENTRY DisplayClientWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
  102. /*
  103. **  Window proc for main window
  104. **  -- passes most stuff to active child window via WmClientCmdProc
  105. **  -- passes DDE messages to DDEProc
  106. */
  107. {
  108.     HDC     hdcScreen ;
  109.     SIZEL   sizlPage ;
  110.     static BYTE abStackGnu[8192] ;
  111.     static BYTE abStackDraw[8192] ;
  112.     TID     tidDraw, tidSpawn ;
  113.     ULONG   ulCount ;
  114.         
  115.     switch (message) {
  116.  
  117.         case WM_CREATE:
  118.  
  119.                 // set initial font
  120.             strcpy( szFontNameSize, INITIAL_FONT ) ;
  121.                 // spawn gnuplot in its own window
  122.             hWndstart = hWnd ;  /* used in spawngnu for errors */ 
  123.             DosCreateThread( &tidSpawn, (PFNTHREAD)SpawnGnu, 0L, 0L, 8192L ) ;
  124.                 // create a dc and hps to draw on the screen
  125.             hdcScreen = WinOpenWindowDC( hWnd ) ;
  126.             sizlPage.cx = 4096 ; sizlPage.cy = 4096 ;
  127.             hpsScreen = GpiCreatePS( hab, hdcScreen, &sizlPage,
  128.                            PU_ARBITRARY|GPIT_MICRO|GPIA_ASSOC) ;
  129.                 // spawn a thread to do the drawing, controlled by sems
  130.             DosCreateMutexSem( NULL, &semCommands, 0L, 0L ) ;
  131.             DosCreateEventSem( NULL, &semStartDraw, 0L, 0L ) ;
  132.             DosCreateEventSem( NULL, &semDrawDone, 0L, 0L ) ;
  133.             DosPostEventSem( semDrawDone ) ;         // so we clear screen 
  134.             DosResetEventSem( semStartDraw, &ulCount ) ;
  135.             bStopDraw = FALSE ;
  136.             bExist = TRUE ;
  137.             DosCreateThread( &tidDraw, (PFNTHREAD)ThreadDraw, 0L, 0L, 8192L ) ;
  138.  
  139.             break ;
  140.             
  141.  
  142.         case WM_COMMAND:
  143.  
  144.             return WmClientCmdProc( hWnd , message , mp1 , mp2 ) ;
  145.  
  146.         case WM_CLOSE:
  147.  
  148.             if( WinSendMsg( hWnd, WM_USER_PRINT_QBUSY, 0L, 0L ) != 0L ) {
  149.                 WinMessageBox( HWND_DESKTOP,
  150.                                hWnd, 
  151.                                "Still printing - not closed",
  152.                                "Gnushell",
  153.                                0,
  154.                                MB_OK | MB_ICONEXCLAMATION ) ;
  155.                 return 0L ;
  156.                 }
  157.                  // kill drawing thread
  158.             bExist = FALSE ;
  159.             DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ;
  160.                 // kill gnuplot if still arounsd
  161.             if( pidGnu != 0L ) DosStopSession( 0, pidGnu ) ;
  162.               return (WinDefWindowProc(hWnd, message, mp1, mp2));
  163.  
  164.         case WM_PAINT:
  165.  
  166.             DoPaint( hWnd, hpsScreen ) ;
  167.             break ;     
  168.  
  169.         case WM_SIZE :
  170.             
  171.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  172.             break ;
  173.  
  174.         case WM_USER_PRINT_BEGIN:
  175.         case WM_USER_PRINT_OK :
  176.         case WM_USER_DEV_ERROR :
  177.         case WM_USER_PRINT_ERROR :
  178.         case WM_USER_PRINT_QBUSY :
  179.  
  180.             return( PrintCmdProc( hWnd, message, mp1, mp2 ) ) ;
  181.  
  182.         case WM_GNUPLOT:
  183.                 // display the plot         
  184.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  185.             WinSendMsg( hWnd, WM_PAINT, 0L, 0L ) ;
  186.             return 0L ;
  187.  
  188.         case WM_GNU_NOHELP:
  189.                 // no gnuplot.gih found
  190.             WinMessageBox( HWND_DESKTOP,
  191.                            hWnd,
  192.                            "Can't find environment variable GNUHELP - no help",
  193.                            "Gnushell",
  194.                            0,
  195.                            MB_OK | MB_ICONEXCLAMATION ) ;
  196.             return 0L ;
  197.  
  198.         case WM_GNU_NOEXE:
  199.                 // no gnuplot.exe found
  200.             WinMessageBox( HWND_DESKTOP,
  201.                            hWnd,
  202.                            "Can't find Gnuplot exe file !!",
  203.                            "Gnushell",
  204.                            0,
  205.                            MB_OK | MB_ICONEXCLAMATION ) ;    
  206.             WinPostMsg( hWnd, WM_CLOSE, 0L, 0L ) ;    
  207.             return 0L ;
  208.  
  209.     default:         /* Passes it on if unproccessed    */
  210.         return (WinDefWindowProc(hWnd, message, mp1, mp2));
  211.     }
  212.     return (NULL);
  213. }
  214.  
  215. MRESULT WmClientCmdProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
  216. /*
  217. **   Handle client window command (menu) messages
  218. **   -- mostly passed on to active child window
  219. **
  220. */
  221.     {
  222.     ULONG usDlg ;
  223.     extern HWND hApp ;
  224.  
  225.     switch( (USHORT) SHORT1FROMMP( mp1 ) ) {
  226.                 
  227.         case IDM_ABOUT :    /* show the 'About' box */
  228.              
  229.             WinDlgBox( HWND_DESKTOP,
  230.                        hwndFrame , 
  231.                        (PFNWP)About ,
  232.                        0L,
  233.                        ID_ABOUT, 
  234.                        NULL ) ;
  235.             break ;
  236.  
  237.  
  238.         case IDM_PRINT:
  239.             if( (usDlg = WinDlgBox( HWND_DESKTOP,
  240.                                    hwndFrame , 
  241.                                    (PFNWP)PrintDlgProc ,
  242.                                    0L,
  243.                                    ID_PRINT, 
  244.                                    szPrintFile )) != DID_CANCEL ) {
  245.                 WinPostMsg( hWnd, WM_COMMAND, (MPARAM)usDlg, 0L ) ; 
  246.                 }
  247.             break ;
  248.  
  249.         case IDM_LINES:
  250.                 // change line setting
  251.             bLineTypes = !bLineTypes ;
  252.             ChangeCheck( hWnd, IDM_LINES, bLineTypes?IDM_LINES:0 ) ;
  253.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  254.             break ;
  255.  
  256.         case IDM_COLOURS:
  257.                 // change colour setting
  258.             bColours = !bColours ;        
  259.             ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
  260.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  261.             break ;
  262.             
  263.         case IDM_PRINTPIC:
  264.             WinPostMsg( hWnd, WM_USER_PRINT_BEGIN, 0L, 0L  ) ;
  265.             break ;
  266.             
  267.         case IDM_PRINTSETUP:
  268.             SetupPrinter( hWnd ) ;
  269.             break ;
  270.  
  271.         case IDM_FONTS:
  272.         
  273.             usDlg = WinDlgBox( HWND_DESKTOP,
  274.                                hwndFrame , 
  275.                                (PFNWP)QFontDlgProc ,
  276.                                0L,
  277.                                IDD_FONTS, 
  278.                                szFontNameSize ) ;
  279.             if( usDlg == DID_OK ) 
  280.                 WinInvalidateRect( hWnd, NULL, TRUE ) ;
  281.         
  282.             break ;
  283.             
  284.         case IDM_HELPFORHELP:
  285.             WinSendMsg(WinQueryHelpInstance(hWnd),
  286.                        HM_DISPLAY_HELP, 0L, 0L ) ;
  287.             return 0L ;
  288.  
  289.         case IDM_EXTENDEDHELP:
  290.             WinSendMsg(WinQueryHelpInstance(hWnd),
  291.                         HM_EXT_HELP, 0L, 0L);
  292.             return 0L ;
  293.  
  294.         case IDM_KEYSHELP:
  295.             WinSendMsg(WinQueryHelpInstance(hWnd),
  296.                        HM_KEYS_HELP, 0L, 0L);
  297.             return 0L ;
  298.  
  299.         case IDM_HELPINDEX:
  300.             WinSendMsg(WinQueryHelpInstance(hWnd),
  301.                        HM_HELP_INDEX, 0L, 0L);
  302.             return 0L ;
  303.  
  304.  
  305.         default : 
  306.     
  307.             return WinDefWindowProc( hWnd, message, mp1, mp2 ) ;
  308.  
  309.         }  
  310.     return( NULL ) ;
  311.     }                      
  312.  
  313. static void DoPaint( HWND hWnd, HPS hps  ) 
  314. /*
  315. **  Paint the screen with current data 
  316. */
  317.     {
  318.     RECTL rectClient ;
  319.     ULONG ulCount ;    
  320.     bStopDraw = TRUE ;    // stop any drawing in progress and wait for 
  321.                           // thread to signal completion 
  322.     DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ;
  323.     DosResetEventSem( semDrawDone, &ulCount ) ;
  324.     WinBeginPaint( hWnd , hps, NULL ) ;
  325.     DosPostEventSem( semStartDraw ) ;  // start drawing
  326.     WinEndPaint( hps ) ;
  327.     }
  328.  
  329. static void ThreadDraw( )
  330. /*
  331. **  Thread to draw plot
  332. */
  333.     {
  334.     HAB  hab ;
  335.     RECTL rectClient ;
  336.     ULONG ulCount ;
  337.  
  338.         /* initialize and wait until ready to draw */
  339.     
  340.     hab = WinInitialize( 0 ) ;
  341. //    DosWaitEventSem( semStartDraw, SEM_INDEFINITE_WAIT ) ;
  342.  
  343.         /* ok - draw until window is destroyed */
  344.  
  345.     while( bExist )  {
  346.  
  347.                 // indicate access to window 
  348.         DosWaitEventSem( semStartDraw, SEM_INDEFINITE_WAIT ) ;
  349.         DosResetEventSem( semStartDraw, &ulCount ) ;
  350.  
  351.                 // will be set TRUE if we decide to stop in the middle, but now
  352.         bStopDraw = FALSE ;         
  353.         
  354.         GpiResetPS( hpsScreen, GRES_ALL ) ;        
  355.         WinQueryWindowRect( hApp, (PRECTL)&rectClient ) ;
  356.         GpiSetPageViewport( hpsScreen, &rectClient ) ;
  357.  
  358.         WinFillRect( hpsScreen, &rectClient, CLR_WHITE ) ;
  359.  
  360.         ScalePS( hpsScreen, &rectClient, 0 ) ;
  361.         
  362.         PlotThings( hpsScreen, 0L ) ;
  363.                 // ok, say that we did it
  364.         DosPostEventSem( semDrawDone ) ;
  365.         }
  366.    
  367.     WinTerminate( hab ) ;
  368.     }
  369.  
  370.  
  371. enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode;
  372.  
  373. void PlotThings( HPS hps, long lColour ) 
  374. /*
  375. **  Plot a spectrum and related graphs on the designated presentation space
  376. **
  377. **  Input:
  378. **          HPS hps         -- presentation space handle of plot ps
  379. **          long lColour    -- number of physical colours, used mainly by
  380. **                             printer drivers to set black & white mode.
  381. **                             If 0, assume screen display
  382. **
  383. **  Note: use semaphore to prevent access to command list while
  384. **        pipe thread is reallocating the list.
  385. */
  386.     {
  387.     int i, lt, ta, col, sl, n, x, y, cx, cy, width ;
  388.     int icnow ;
  389.     char *str, *buf ;
  390.     long sw ;
  391.     POINTL ptl ;
  392.     POINTL aptl[4] ;    
  393.     long lCurCol ;
  394.     BOOL bBW ;
  395.     GRADIENTL grdl ;
  396.     BOOL bHorz = TRUE ;
  397.     SIZEF sizHor, sizVer ;
  398.         /* sometime, make these user modifiable... */
  399.     static long lLineTypes[7] = { LINETYPE_SOLID,
  400.                                   LINETYPE_SHORTDASH,
  401.                                   LINETYPE_DOT,
  402.                                   LINETYPE_DASHDOT,
  403.                                   LINETYPE_LONGDASH,
  404.                                   LINETYPE_DOUBLEDOT,
  405.                                   LINETYPE_DASHDOUBLEDOT } ;
  406.     static long lCols[15] =     { CLR_BLACK,
  407.                                   CLR_DARKGRAY,
  408.                                   CLR_BLUE,
  409.                                   CLR_RED,
  410.                                   CLR_GREEN,
  411.                                   CLR_CYAN,
  412.                                   CLR_PINK,
  413.                                   CLR_YELLOW,
  414.                                   CLR_DARKBLUE,
  415.                                   CLR_DARKRED,
  416.                                   CLR_DARKGREEN,
  417.                                   CLR_DARKCYAN,
  418.                                   CLR_DARKPINK,
  419.                                   CLR_BROWN,
  420.                                   CLR_PALEGRAY } ;
  421.  
  422.     if( lColour== 1 || lColour == 2 ) bBW = TRUE ;
  423.     else bBW = FALSE ;
  424.     
  425.    /* loop over accumulated commands from inboard driver */
  426.  
  427.     for( i=0; !bStopDraw && i<ic; i++ ) {
  428.  
  429.             DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ;
  430.             buf = commands[i];
  431.             DosReleaseMutexSem( semCommands ) ;
  432.  
  433.       /*   PM_vector(x,y) - draw vector  */
  434.             if (*buf == 'V') { 
  435.              sscanf(buf, "V%4d%4d", &x, &y);  
  436.                  ptl.x = (LONG)x ; ptl.y = (LONG)y ;
  437.                  GpiLine( hps, &ptl ) ;
  438.              }
  439.  
  440.       /*   PM_move(x,y) - move  */
  441.             else if (*buf == 'M')  {
  442.                 sscanf(buf, "M%4d%4d", &cx, &cy);  
  443.                 ptl.x = (LONG)cx ; ptl.y = (LONG)cy ;
  444.                 GpiMove( hps, &ptl ) ;
  445.                 }
  446.         
  447.       /*   PM_put_text(x,y,str) - draw text   */
  448.             else if (*buf == 'T') { 
  449.             sscanf(buf, "T%4d%4d", &x, &y);  
  450.             str = buf + 9; sl = strlen(str) ;
  451.                 lCurCol = GpiQueryColor( hps ) ;
  452.                 GpiSetColor( hps, CLR_BLACK ) ;
  453.                 GpiQueryTextBox( hps, (LONG)strlen( str ), str, 4L, aptl ) ;
  454.                 if( bHorz ) sw = aptl[3].x ;
  455.                 else sw = aptl[3].y ;
  456.                 switch(jmode) {
  457.                 case LEFT:   sw = 0;     break;
  458.                 case CENTRE: sw = -sw/2; break;
  459.                 case RIGHT:  sw = -sw;   break;
  460.                     }
  461.                 if( bHorz ) {
  462.                     ptl.x = (LONG)(x+sw) ; ptl.y = (LONG)y ;
  463.                     }
  464.                 else {
  465.                     ptl.x = (LONG)x ; ptl.y = (LONG)(y+sw) ;
  466.                     }
  467.                 GpiCharStringAt( hps, &ptl, (LONG) strlen( str ) , str ) ;
  468.                 GpiSetColor( hps, lCurCol ) ;
  469.             }
  470.  
  471.       /*   PM_justify_text(mode) - set text justification mode  */
  472.             else if (*buf == 'J') 
  473.                 sscanf(buf, "J%4d", &jmode);
  474.  
  475.       /*   PM_linetype(type) - set line type  */
  476.       /* mapped to colour */
  477.             else if (*buf == 'L') { 
  478.             sscanf(buf, "L%4d", <);
  479.         /* linetype = -2 axes, -1 border, 0 arrows, all to 0 */
  480.             col = lt ;
  481.                 if( lt < 0 ) lt = 0 ;
  482.             lt = (lt%8);
  483.             col = (col+2)%16 ;
  484. //            width = (lt == 0) ? 2 : 0;
  485.                 if( bLineTypes || bBW ) {
  486.                     GpiSetLineType( hps, lLineTypes[lt] ) ;
  487.                     }
  488.                 if( !bBW )  /* maintain some flexibility here in case we don't want
  489.                            the model T option */ 
  490.                     if( bColours ) GpiSetColor( hps, lCols[col] ) ;
  491.                     else GpiSetColor( hps, CLR_BLACK ) ;
  492.                 }
  493.  
  494.       /*   PM_text_angle(ang) - set text angle, 0 horz, 1 vert  */
  495.             else if (*buf == 'A') { 
  496.             sscanf(buf, "A%4d", &ta);
  497.                 if( ta == 0 ) {
  498.                     grdl.x = 0L ; grdl.y = 0L ;
  499.                     GpiSetCharAngle( hps, &grdl ) ;
  500.                     if( !bHorz ) {
  501.                         GpiQueryCharBox( hps, &sizVer ) ;
  502.                         sizHor.cx = sizVer.cy ; sizHor.cy = sizVer.cx ;
  503.                         GpiSetCharBox( hps, &sizHor ) ;
  504.                         bHorz = TRUE ;
  505.                         }
  506.                     }
  507.                 else if( ta == 1 ) {
  508.                     grdl.x = 0L ; grdl.y = 1L ;
  509.                     GpiSetCharAngle( hps, &grdl ) ;
  510.                     if( bHorz ) {
  511.                         GpiQueryCharBox( hps, &sizHor ) ;
  512.                         sizVer.cx = sizHor.cy ; sizVer.cy = sizHor.cx ;
  513.                         GpiSetCharBox( hps, &sizVer ) ;
  514.                         bHorz = FALSE ;
  515.                         }
  516.                     }
  517.                 else continue ;            
  518.                 }
  519.             }
  520.     }
  521.     
  522. short ScalePS( HPS hps, PRECTL prect, USHORT usFlags )
  523. /*
  524. **  Get a font to use
  525. **  Scale the plot area to world coords for subsequent plotting
  526. */
  527.     {
  528.     RECTL rectView, rectClient ;
  529.     SIZEL sizePage ;
  530.     static char *szFontName ;
  531.     static short shFontSize ;
  532.     static long lcid = 1L ;
  533.         
  534.     rectClient = *prect ;
  535.     sizePage.cx = 4096L ; 
  536.     sizePage.cy = 4096L ; 
  537.  
  538.     sscanf( szFontNameSize, "%d", &shFontSize ) ;
  539.     szFontName = strchr( szFontNameSize, '.' ) + 1 ;
  540.     rectView.xLeft = 0L ;
  541.     rectView.xRight = sizePage.cx ;
  542.     rectView.yBottom = 0L ; rectView.yTop = sizePage.cy ;
  543.     GpiSetPS( hps, &sizePage, PU_ARBITRARY ) ;
  544.     GpiSetPageViewport( hps, &rectClient ) ;
  545.     SelectFont( hps, szFontName, shFontSize, lcid ) ;
  546.     GpiSetGraphicsField( hps, &rectView ) ;
  547.     return 0 ;
  548.     }
  549.  
  550. void SelectFont( HPS hps, char *szFont, short shPointSize, long lcid )
  551. /*
  552. **  Select a named and sized outline (adobe) font
  553. */
  554.     {
  555.      HDC         hdc ;
  556.      static FATTRS fat ;
  557.      LONG   xDeviceRes, yDeviceRes ;
  558.      POINTL ptlFont ;
  559.      SIZEF  sizfx ;
  560.  
  561.      fat.usRecordLength  = sizeof fat ;
  562.      fat.fsSelection     = 0 ;
  563.      fat.lMatch          = 0 ;
  564.      fat.idRegistry      = 0 ;
  565.      fat.usCodePage      = GpiQueryCp (hps) ;
  566.      fat.lMaxBaselineExt = 0 ;
  567.      fat.lAveCharWidth   = 0 ;
  568.      fat.fsType          = 0 ;
  569.      fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
  570.                            FATTR_FONTUSE_TRANSFORMABLE ;
  571.  
  572.      strcpy (fat.szFacename, szFont) ;
  573.  
  574.      GpiCreateLogFont (hps, NULL, lcid, &fat) ;
  575.      GpiSetCharSet( hps, lcid ) ;
  576.  
  577.      hdc = GpiQueryDevice (hps) ;
  578.  
  579.      DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes) ;
  580.      DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION,   1L, &yDeviceRes) ;
  581.  
  582.                          // Find desired font size in pixels
  583.  
  584.      ptlFont.x = 254L * (long)shPointSize * xDeviceRes / 720000L ;
  585.      ptlFont.y = 254L * (long)shPointSize * yDeviceRes / 720000L ;
  586.  
  587.                          // Convert to page units
  588.  
  589.      GpiConvert (hps, CVTC_DEVICE, CVTC_PAGE, 1L, &ptlFont) ;
  590.  
  591.                          // Set the character box
  592.  
  593.      sizfx.cx = MAKEFIXED (ptlFont.x, 0) ;
  594.      sizfx.cy = MAKEFIXED (ptlFont.y, 0) ;
  595.  
  596.      GpiSetCharBox (hps, &sizfx) ;
  597.     }
  598.  
  599. void SpawnGnu()
  600. /*
  601. ** Spawn gnuplot in a command-line window and open a named pipe 
  602. ** for graphics commands
  603. ** Error messages must be posted, not sent, as this is a new thread.
  604. ** (We could open our own message queue for such, but why bother?). 
  605. */
  606.     {
  607.     HPIPE hRead ; 
  608.     static char buf[130] ; 
  609.     char *szEnv ;
  610.     char *szFileBuf ;
  611.     char *envpt, *pget ; 
  612.     USHORT pid, rc, usErr ;
  613.     ULONG cbR ;
  614.     STARTDATA start ;
  615.     USHORT i ;
  616.     PID ppid ;
  617.     char buff[2] ;
  618.  
  619.     DosEnterCritSec() ;
  620.     szFileBuf = malloc(CCHMAXPATHCOMP) ;
  621.     DosExitCritSec() ;
  622.     if( szFileBuf == NULL ) return ;
  623.     // 2048 bytes for environment should suffice, 
  624.     // but need better allocation method
  625.  
  626.     DosEnterCritSec() ;
  627.     szEnv = malloc(2048) ;
  628.     DosExitCritSec() ;
  629.     if( szEnv == NULL ) return ;
  630.     
  631.             /* open a named pipe for communication with gnuplot */
  632.  
  633.     rc = DosCreateNPipe( GNUPIPE,
  634.                          &hRead, 
  635.                          NP_ACCESS_DUPLEX|NP_NOINHERIT|NP_NOWRITEBEHIND ,
  636.                          1|NP_WAIT|NP_READMODE_BYTE|NP_TYPE_BYTE,
  637.                          1024,
  638.                          1024,
  639.                          60000L) ;
  640.  
  641.             /* spawn gnuplot */
  642.             
  643.         /* first, build the environment: will use existing if
  644.            available, else attempts to make its own           */
  645.  
  646.     strcpy( szEnv, ENVGNUHELP ) ; strcat( szEnv, "=" ) ;
  647.     if( ( envpt = getenv( ENVGNUHELP ) )  != NULL )
  648.         strcat( szEnv, envpt ) ;
  649.     else {
  650.         rc = DosSearchPath( SEARCH_CUR_DIRECTORY,  /* try here */
  651.                             "PATH",
  652.                             GNUHELPFILE,
  653.                             szFileBuf,
  654.                             256L ) ; 
  655.         if( rc == 0 ) {
  656.             strcat( szEnv, szFileBuf ) ;
  657.             }
  658.         else
  659.             WinPostMsg( hWndstart, WM_GNU_NOHELP, 0L, 0L ) ;    
  660.         }
  661.  
  662.     envpt = szEnv + strlen( szEnv ) +1 ;
  663.     strcpy( envpt, GNUTERMINIT ) ;    
  664.     envpt = envpt + strlen( envpt ) +1 ;
  665.     strcpy( envpt, "COMSPEC=" ) ;
  666.     envpt = envpt + strlen( envpt ) ;
  667.     strcat( envpt, getenv( "COMSPEC" ) ) ;
  668.     envpt = envpt + strlen( envpt ) +1 ; 
  669.     strcpy( envpt, ENVGNUPLOT ) ; strcat( envpt, "=" ) ;
  670.     if( (pget=getenv( ENVGNUPLOT ))!= NULL )
  671.         strcat( envpt, pget ) ;
  672.     else
  673.         strcat( envpt, getcwd( szFileBuf, 256 ) ) ; 
  674.     envpt = envpt + strlen( envpt ) +1 ; 
  675.     strcpy( envpt, "PATH=" ) ;  // need path for execed command shells
  676.     if( (pget=getenv( "PATH" ))!= NULL )
  677.         strcat( envpt, pget ) ;
  678.     envpt = envpt + strlen( envpt ) +1 ; 
  679.     *envpt = 0 ;
  680.             
  681.             /* find exe file */ 
  682.   
  683.     rc = DosSearchPath( SEARCH_ENVIRONMENT, /* search gnuplot env */
  684.                         ENVGNUPLOT,
  685.                         GNUEXEFILE,
  686.                         szFileBuf,
  687.                         256L ) ; 
  688.  
  689.     if( rc != 0 ) 
  690.         rc = DosSearchPath( SEARCH_CUR_DIRECTORY|SEARCH_ENVIRONMENT,  /* then try path */
  691.                             "PATH",
  692.                             GNUEXEFILE,
  693.                             szFileBuf,
  694.                             256L ) ; 
  695.                             
  696.     if( rc != 0 ) {         /* can't fine gnuplot exe ! */
  697.         WinPostMsg( hWndstart, WM_GNU_NOEXE, 0L, 0L ) ;    
  698.         return ;
  699.         }
  700.  
  701.             /* start a new windowed session on the desktop */
  702.    
  703.     start.Length = sizeof(STARTDATA) ;
  704.     start.Related = TRUE ;
  705.     start.FgBg = FALSE ;
  706.     start.TraceOpt = 0 ;
  707.     start.PgmTitle = "Gnushell: Commands" ;
  708.     start.PgmName = szFileBuf ;
  709.     start.PgmInputs = "" ;
  710.     start.TermQ = "" ;
  711.     start.Environment = szEnv ;
  712.     start.InheritOpt = 0 ;
  713.     start.SessionType = 2 ;
  714.     start.IconFile = "" ;
  715.     start.PgmHandle = 0L ;
  716.     start.PgmControl = 32768 ;
  717.     start.InitXPos = 0;//20;
  718.     start.InitYPos = 0;//20;
  719.     start.InitXSize = 0;//600;
  720.     start.InitYSize = 0;//200;
  721.     start.ObjectBuffer = NULL ;
  722.     start.ObjectBuffLen = 0L ;
  723.  
  724.     DosStartSession( &start, &pidGnu, &ppid ) ;
  725.  
  726.     DosEnterCritSec() ;
  727.     free( szFileBuf ) ;
  728.     free( szEnv ) ;
  729.     DosExitCritSec() ;
  730.     
  731.         /* attach to gnuplot */
  732.  
  733.     DosConnectNPipe( hRead ) ;
  734.  
  735.         /* store graphics commands */
  736.         /* use semaphore to prevent problems with drawing while reallocating
  737.            the command buffers */
  738.  
  739.     while ( 1) {
  740.     i = 0 ;    
  741.     while((usErr=DosRead(hRead,buff, 1, &cbR))==0) {
  742.         if( buff[0] == 0x0a || buff[0] == 0x0d ) {
  743.             buf[i] = 0 ; break ; }
  744.         else buf[i++] = buff[0] ;
  745.         }
  746.     if( usErr != 0 ) break ;
  747.  
  748.      if (*buf == 'G') {                         /* enter graphics mode */
  749.                 /* wait for access to command list and lock it */
  750.          DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ;
  751.          DosEnterCritSec() ;
  752.      if (commands!=NULL) {    // delete all old commands and prepare for new
  753.         int i; 
  754.         for(i=0; i<=ic ;i++ ) 
  755.             free(commands[i]);
  756.         free(commands);
  757.         }
  758.      commands = NULL; ncalloc = 0; ic = 0 ;
  759.          DosExitCritSec() ;
  760.          DosReleaseMutexSem( semCommands ) ;
  761.          }
  762.       else if (*buf == 'E') { Display() ; }     /* plot graph */
  763.       else if (*buf == 'R') { break ; }         /* leave gnushell */
  764.                 /* otherwise store command, allocating memory if necc.
  765.                    using really messy scheme to get round 64K limit to
  766.                    realloc [must rewrite for 2.0 !] */
  767.       else {                         
  768.      if (ic >= ncalloc) {
  769.              DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ;
  770.              DosEnterCritSec() ;
  771.              ncalloc = ncalloc + 4096 ;
  772.          commands = (char**)realloc(commands, ncalloc*sizeof(char*)) ;
  773.              DosExitCritSec() ;
  774.              DosReleaseMutexSem( semCommands ) ;
  775.          }
  776.       commands[ic] = strdup(buf);
  777.       ic++ ;
  778.       }
  779.       }
  780.     pidGnu = 0 ; /* gnuplot has shut down ... */
  781.     WinPostMsg( hApp, WM_CLOSE, 0L, 0L ) ;    
  782.     }
  783.  
  784. static void Display()
  785. /*
  786. **  Display gnuplot results 
  787. **  -- must post message as this thread is not drawing thread
  788. */
  789.     {
  790.     WinPostMsg( hApp, WM_GNUPLOT, 0L, 0L ) ;    
  791.     }
  792.